/* 陀螺仪控制组件 */

/**
 * 陀螺仪插件
 * 用于监听设备陀螺仪数据并处理移动计算
 * 支持H5平台
 */
class GyroscopePlugin {
  constructor(options = {}) {
    this.isTracking = false; // 是否正在追踪
    this.isCalibrating = false; // 是否已校准
    this.zeroOffset = { x: 0, y: 0, z: 0 }; // 校准偏移值
    this.lastPosition = { x: 0, y: 0, z: 0 }; // 上一次位置
    this.moveData = { x: 0, y: 0, z: 0 }; // 移动距离
    this.threshold = options.threshold || 0.1; // 移动阈值
    this.onDataChange = options.onDataChange || null; // 数据变化回调
    this.onError = options.onError || null; // 错误回调
    this.handleDeviceOrientation = this.handleDeviceOrientation.bind(this); // 绑定上下文
  }

  /**
   * 开始追踪陀螺仪数据
   */
  start() {
    // 检查浏览器支持
    if (!window.DeviceOrientationEvent) {
      const errorMsg = "您的设备不支持陀螺仪";
      this.handleError(errorMsg);
      return false;
    }

    // 请求权限（iOS 13+ 需要）
    if (typeof DeviceOrientationEvent.requestPermission === "function") {
      DeviceOrientationEvent.requestPermission()
        .then((permissionState) => {
          if (permissionState === "granted") {
            this.addDeviceOrientationListener();
          } else {
            const errorMsg = "用户拒绝授权陀螺仪权限";
            this.handleError(errorMsg);
          }
        })
        .catch((error) => {
          this.handleError("请求陀螺仪权限失败: " + error.message);
        });
    } else {
      this.addDeviceOrientationListener();
    }

    return true;
  }

  /**
   * 添加设备方向监听
   */
  addDeviceOrientationListener() {
    this.isTracking = true;
    this.lastPosition = { x: 0, y: 0, z: 0 };
    window.addEventListener("deviceorientation", this.handleDeviceOrientation);
  }

  /**
   * 处理设备方向数据
   */
  handleDeviceOrientation(res) {
    console.log('开始监听设备方向数据',res);
    // 正常h5段设备方向： beta=x轴，gamma=y轴，alpha=z轴
    // 确保角度值在0-360范围内
    const alpha = res.alpha || 0;
    const beta = res.beta || 0;
    const gamma = res.gamma || 0;
    
    // 构建新的设备数据对象
    const deviceData = {
      x: -alpha || 0,
      y: -beta || 0,
      z: -gamma || 0
    };
    
    if (!this.isCalibrating && deviceData.x !== undefined) {
      // 初始化校准偏移
      this.zeroOffset.x = deviceData.x;
      this.zeroOffset.y = deviceData.y;
      this.zeroOffset.z = deviceData.z;
      this.isCalibrating = true;
      // 初始化lastPosition，避免首次计算差值时的问题
      this.lastPosition = {
        x: deviceData.x,
        y: deviceData.y,
        z: deviceData.z
      };
    } else {
      // 应用校准偏移
      const calibratedData = {
        x: deviceData.x - this.zeroOffset.x,
        y: deviceData.y - this.zeroOffset.y,
        z: deviceData.z - this.zeroOffset.z
      };
      
      // 处理校准后的数据
      this.handleMovement(calibratedData);
    }
  }

  /**
   * 处理移动数据
   */
  handleMovement(data) {
    // 获取上一位置
    const prevX = this.lastPosition.x || 0;
    const prevY = this.lastPosition.y || 0;
    const prevZ = this.lastPosition.z || 0;
    
    // 计算差值，处理360度循环
    const deltaX = this.calculateAngleDifference(data.x, prevX);
    const deltaY = this.calculateAngleDifference(data.y, prevY);
    const deltaZ = this.calculateAngleDifference(data.z, prevZ);
    
    // 更新移动数据
    this.moveData.x = deltaX;
    this.moveData.y = deltaY;
    this.moveData.z = deltaZ;

    // 更新最后位置
    this.lastPosition = { ...data };
    
    // 计算总移动量
    const totalMovement = Math.sqrt(
      deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ
    );
    
    // 只有当移动量超过阈值时才触发回调
    if (totalMovement > this.threshold) {
      this.notifyDataChange();
    }
  }

  /**
   * 计算360度循环的角度差值
   */
  calculateAngleDifference(current, previous) {
    let diff = current - previous;
    // 如果差值超过180度，说明应该从另一个方向计算
    if (Math.abs(diff) > 180) {
      // 根据正负方向调整差值
      diff = diff > 0 ? diff - 360 : diff + 360;
    }
    return diff;
  }

  /**
   * 触发数据变化回调
   */
  notifyDataChange() {
    if (this.onDataChange) {
      this.onDataChange({ ...this.moveData });
    }
  }

  /**
   * 处理错误
   */
  handleError(message) {
    if (this.onError) {
      this.onError(message);
    } else {
      console.error(message);
    }
  }

  /**
   * 停止追踪陀螺仪数据
   */
  stop() {
    this.isTracking = false;
    this.isCalibrating = false;
    window.removeEventListener("deviceorientation", this.handleDeviceOrientation);
    // 重置数据
    this.moveData.x = 0;
    this.moveData.y = 0;
    this.moveData.z = 0;
    console.log('停止监听设备方向数据');
  }

  /**
   * 获取当前状态
   */
  getStatus() {
    return {
      isTracking: this.isTracking,
      isCalibrating: this.isCalibrating,
      moveData: { ...this.moveData },
      zeroOffset: { ...this.zeroOffset }
    };
  }

  /**
   * 重新校准
   */
  recalibrate() {
    this.isCalibrating = false;
  }

  /**
   * 切换追踪状态
   */
  toggle() {
    if (this.isTracking) {
      this.stop();
    } else {
      this.start();
    }
    return this.isTracking;
  }
}

// 导出插件
export { GyroscopePlugin };